-- ScrollTool
-- create by dengc
-- 滚动容器循环复用的工具函数

module("ScrollTool", package.seeall);

-- 注册一个委托事件
function addEventListener(scrollNode, func)
    local eventList = scrollNode.eventList or {};
    table.insert(eventList, func);
    scrollNode.eventList = eventList;

    local function eventListener(sender, eventType)
        local eventList = scrollNode.eventList;
        for _, func in ipairs(eventList) do
            func(sender, eventType);
        end
    end
    scrollNode:addEventListener(eventListener);
end

function removeEventListener(scrollNode)
    scrollNode.eventList = {};
    local function emptyListener(sender, eventType)
    end
    scrollNode:addEventListener(emptyListener);
end

-------------------------------------------------------------------------------
-- 初始化滚动容器内的单元格（仅针对横向滚动容器）
-- @param windowNode    界面节点
-- @param scrollNode    容器节点
-- @param itemNode      单元格的节点
-- @param totalNum      单元格总数
-- @param maxRowNum     最大行数
-- @param wGap          单元格间距(横向) 这里作为最小值使用
-- @param hGap          单元格间距(纵向)
-- @param iconWidth     单元格宽度
-- @param iconHeight    单元格高度
-- @param topHGap       上方留白
-- @param leftWGap      左右留白  这里作为最小值使用
-- @param touchEvent    点击事件注册函数
-- @param initHandle    格子初始化委托
function initScrollGridsHorizontal(windowNode, scrollNode, itemNode, totalNum, maxRowNum, wGap, hGap, iconWidth, iconHeight, topHGap, leftWGap, rightWGap, touchEvent, initHandle)

    removeEventListener(scrollNode);

    local w = DESIGN_WIDTH;
    local h = DESIGN_HEIGHT;

    -- 单页最大容纳的列数
    local pageColNum = math.floor((scrollNode:getContentSize().width - leftWGap - rightWGap) / (iconWidth + wGap));

    -- 计算单元格分布情况
    -- 开启循环复用时，gridList[x][y]:x为列，y为行
    -- 关闭循环复用时，gridList[x][y]:x为行，y为列
    local gridList = sortGrids(totalNum, maxRowNum, pageColNum);

    -- 最大列数
    local maxColNum = #gridList;

    -- 先计算总高度
    local totalHeight = maxRowNum * (iconHeight + hGap) - hGap + topHGap;
    local totalWidth  = maxColNum * (iconWidth + wGap) - wGap + (leftWGap  + rightWGap);

    -- 先获取下显示区域的宽度和高度
    local areaWidth = scrollNode:getInnerContainerSize().width;
    local areaHeight = scrollNode:getInnerContainerSize().height;

    -- 设置滚动区域的尺寸
    scrollNode:setInnerContainerSize(cc.size(totalWidth, scrollNode:getInnerContainerSize().height));

    -- 循环复用
    local widget = replaceNodeWithWidget(itemNode);

    -- 如果所有需要画出来的列数大于当前页面能显示的最大列数加3
    -- 之所以加三，是因为三屏是循环复用组件的必要条件
    if (maxColNum > pageColNum + 3) and initHandle then
        -- 声明变量
        local LOOP_COL_NUM = pageColNum + 3;
        local innerSize = scrollNode:getInnerContainerSize();
        local scrollSize = scrollNode:getContentSize();
        local curColIndex = math.ceil(math.max(scrollNode:getInnerContainer():getPositionX() - leftWGap, 0) / (iconWidth + wGap));
        curColIndex = math.max(curColIndex - 1, 1);
        curColIndex = math.min(curColIndex + LOOP_COL_NUM - 1, maxColNum) - LOOP_COL_NUM + 1;
        curColIndex = math.max(curColIndex, 1);

        -- 初始化
        -- 画出能够进行循环复用的三屏所需的最小列
        for curIndex = curColIndex, curColIndex + LOOP_COL_NUM - 1 do
            for j = 1, #gridList[maxRowNum] do
                local child = widget:clone();
                if touchEvent then
                    touchEvent(windowNode, child);
                end
                scrollNode:addChild(child);
                SetWItemPosition(scrollNode, child, curIndex, j, wGap, iconWidth, hGap, iconHeight, topHGap, maxRowNum, leftWGap);
                gridList[curIndex][j] = initHandle(windowNode, child, (curIndex - 1) * maxRowNum + j);
            end
            curColIndex = curColIndex + 1;
        end
        curColIndex = curColIndex - 1;

        -- 移动循环复用物件
        -- 定时器的实现
        local innerContainer = scrollNode:getInnerContainer();

        -- 向左移动时，超出可视滑动区域1个列宽
        local rightOffset = scrollSize.width + iconWidth + wGap;
        local leftOffset = -(2* iconWidth + wGap + rightWGap);
        local function update()
            -- innerContainer在界面解析的被析构掉了
            if tolua.cast(innerContainer, "ccNode") == nil then
                return;
            end

            -- 渲染组件的列指针
            if curColIndex ~= 1 then
                while true do
                    local flag;

                    -- 向左移动时
                    if (curColIndex < maxColNum) and leftOffset > gridList[curColIndex - LOOP_COL_NUM + 1][1]:getPositionX() + innerContainer:getPositionX() then
                        local temp = {};
                        for i, child in pairs(gridList[curColIndex - LOOP_COL_NUM + 1]) do
                            temp[i] = child;
                        end

                        -- 把最右边一列的组件取出，渲染到最左边
                        for i, child in pairs(temp) do
                            child.index = curColIndex * maxRowNum + i;
                            child:setName("item" .. curColIndex * maxRowNum + i);
                            if touchEvent then
                                touchEvent(windowNode, child);
                            end
                            SetWItemPosition(scrollNode, child, curColIndex + 1, i, wGap, iconWidth, hGap, iconHeight, topHGap, maxRowNum, leftWGap);
                            gridList[curColIndex + 1][i] = initHandle(windowNode, child, curColIndex * maxRowNum + i);
                        end

                        -- 列指针加1
                        curColIndex = curColIndex + 1;

                        flag = true;

                    -- 向右移动时
                    elseif (curColIndex > LOOP_COL_NUM) and rightOffset < gridList[curColIndex][1]:getPositionX() + innerContainer:getPositionX() then
                        -- 列指针减1
                        local temp = {};
                        for i, child in pairs(gridList[curColIndex]) do
                            temp[i] = child;
                        end

                        curColIndex = curColIndex - 1;

                        -- 把最左边一列的组件取出，渲染到最右边
                        for i, child in pairs(temp) do
                            child.index = (curColIndex - LOOP_COL_NUM) * maxRowNum + i;
                            child:setName("item" .. (curColIndex - LOOP_COL_NUM) * maxRowNum + i);
                            if touchEvent then
                                touchEvent(windowNode, child);
                            end
                            SetWItemPosition(scrollNode, child, curColIndex - LOOP_COL_NUM + 1, i, wGap, iconWidth, hGap, iconHeight, topHGap, maxRowNum, leftWGap);
                            gridList[curColIndex - LOOP_COL_NUM + 1][i] = initHandle(windowNode, child, (curColIndex - LOOP_COL_NUM) * maxRowNum + i);
                        end

                        flag = true;
                    end

                    if not flag then
                        break;
                    end
                end
            end
        end

        update(scrollNode);

        local function eventListener(sender,eventType)
            if eventType == ccui.ScrollviewEventType.scrolling then
                update();
            end
        end
        addEventListener(scrollNode, eventListener);

    else
        -- 如果所有需要画出的物件的列数小于等于当前页最大列数加三，那么一次性把物件加载出来即可
        for i = 1, maxColNum do
            for j = 1, #gridList[i] do
                local child = widget:clone();

                if touchEvent then
                    touchEvent(windowNode, child);
                end

                scrollNode:addChild(child);
                SetWItemPosition(scrollNode, child, i, j, wGap, iconWidth, hGap, iconHeight, topHGap, maxRowNum, leftWGap);
                gridList[i][j] = initHandle(windowNode, child, (i - 1) * maxRowNum + j);
            end
        end
    end
end

----------------------------------------------
-- 单元格排序
-- @param totalNum      单元格总数
-- @param maxRowNum     最大行数
-- @param pageColNum    单页可以显示下的列数
function sortGrids(totalNum, maxRowNum, pageColNum)
    local ret = {};
    local maxColNum = math.ceil(totalNum / maxRowNum);

    for i = 1, maxColNum do
        for j = 1, maxRowNum do
            ret[i] = ret[i] or {};
            table.insert(ret[i], j);
        end
    end

    return ret;
end

-------------------------------------------------------------------------------
-- 初始化滚动容器内的单元格（仅针对竖向滚动容器）
-- @param windowNode    界面节点
-- @param scrollNode    容器节点
-- @param itemNode      单元格的节点
-- @param totalNum      单元格总数
-- @param maxColNum     最大列数
-- @param wGap          单元格间距(横向) 这里作为最小值使用
-- @param hGap          单元格间距(纵向)
-- @param iconWidth     单元格宽度
-- @param iconHeight    单元格高度
-- @param topHGap       上方留白
-- @param bottomHGap    下方留白
-- @param leftWGap      左右留白  这里作为最小值使用
-- @param touchEvent    点击事件注册函数
-- @param initHandle    格子初始化委托
-- @param isInvert      是否逆序(从下到上)
function initScrollGridsVertical(windowNode, scrollNode, itemNode, totalNum, maxColNum, wGap, hGap, iconWidth, iconHeight, topHGap, bottomHGap, leftWGap, touchEvent, initHandle, isInvert)

    removeEventListener(scrollNode);
    scrollNode:removeAllChildren();

    local w = DESIGN_WIDTH;
    local h = DESIGN_HEIGHT;

    -- 单页最多容纳的行数
    local pageRowNum = math.floor((scrollNode:getContentSize().height - topHGap - bottomHGap) / (iconHeight + hGap));

    -- 计算单元格分布情况
    local gridList = sortGridsEx(totalNum, pageRowNum, maxColNum);

    -- 行数
    local rowNum = #gridList;
    local colNum = 0;

    -- 取所有行的列数的最大值作为最大列数
    for _, rowList in ipairs(gridList) do
        if type(rowList) == "table" then
            colNum = math.max(colNum, #rowList);
        end
    end

    -- 先计算总高度
    local totalHeight = rowNum * (iconHeight + hGap) - hGap + topHGap + bottomHGap;
    local totalWidth  = colNum * (iconWidth + wGap) - wGap + (leftWGap * 2);

    scrollNode:setInnerContainerSize(cc.size(scrollNode:getInnerContainerSize().width, totalHeight));

    -- 触屏事件
    -- scrollNode:setTouchEnabled(rowNum > pageRowNum);
    scrollNode:setTouchEnabled(true);

    -- 循环复用
    local widget = replaceNodeWithWidget(itemNode);

    -- 如果所有需要画出来的行数大于当前页面能显示的最大行数加3
    -- 之所以加三，是因为三屏是循环复用组件的必要条件
    if (rowNum > pageRowNum + 3) and initHandle then
        -- 声明变量
        local LOOP_ROW_NUM = pageRowNum + 3;
        local innerSize = scrollNode:getInnerContainerSize();
        local scrollSize = scrollNode:getContentSize();
        local curRowIndex = math.ceil(math.max(innerSize.height - scrollSize.height - topHGap + scrollNode:getInnerContainer():getPositionY(), 0) / (iconHeight + hGap));
        curRowIndex = math.max(curRowIndex - 1, 1);
        curRowIndex = math.min(curRowIndex + LOOP_ROW_NUM - 1, rowNum) - LOOP_ROW_NUM + 1;
        curRowIndex = math.max(curRowIndex, 1);

        -- 初始化循环复用的组件
        for curIndex = curRowIndex, curRowIndex + LOOP_ROW_NUM - 1 do
            for j = 1, #gridList[curIndex] do
                local child = widget:clone();
                child.index = (curIndex - 1) * maxColNum + j;
                child:setName("item" .. (curIndex - 1) * maxColNum + j);
                if touchEvent then
                    touchEvent(windowNode, child);
                end
                scrollNode:addChild(child);
                SetHItemPosition(scrollNode, child, curIndex, j, hGap, iconWidth, iconHeight, topHGap, bottomHGap, leftWGap, wGap, maxColNum, isInvert);
                gridList[curIndex][j] = initHandle(windowNode, child, (curIndex - 1) * maxColNum + j);
            end
            curRowIndex = curRowIndex + 1;
        end
        curRowIndex = curRowIndex - 1;

        -- 取得向上移动时，超出可视滑动区域 1 个行高的总高度
        local upOffset = scrollSize.height + iconHeight + hGap;
        local downOffset = -(2 * iconHeight + hGap + bottomHGap);

        -- 移动循环复用物件
        local function update(scrollview)
            local innerContainer = scrollview:getInnerContainer();
            local gridList = scrollview.gridList;
            local curRowIndex = scrollview.curRowIndex;

            if not gridList or not curRowIndex then
                return;
            end

            -- innerContainer在关闭页面的时候可能已经被析构掉了
            if tolua.cast(innerContainer, "ccNode") == nil then
                return;
            end

            -- 当前指针所指向的行
            if curRowIndex ~= 1 then

                while true do
                    local flag;
                    -- 向上移动时，判断缓存池第一个节点的位置超过可视滑动面板 1 个行高时，则将节点移到缓存池最后
                    -- gridList[curRowIndex - LOOP_ROW_NUM + 1][1]:getPositionY() + innerContainer:getPositionY() 为可视滑动区域最底部到该格子的高度
                    -- 如果该高度超过可视滑动区域 1 个行高，则移动该节点
                    if (curRowIndex < rowNum) and upOffset < gridList[curRowIndex - LOOP_ROW_NUM + 1][1]:getPositionY() + innerContainer:getPositionY() then
                        -- 取得缓存池中第一行的节点对象
                        local temp = {};
                        for i, child in pairs(gridList[curRowIndex - LOOP_ROW_NUM + 1]) do
                            temp[i] = child;
                        end

                        -- 把第一行的节点对象移到缓存池最后，并初始化为 curRowIndex + 1 行的内容
                        for i, child in pairs(temp) do
                            child.index = curRowIndex * maxColNum + i;
                            child:setName("item" .. curRowIndex * maxColNum + i);
                            if touchEvent then
                                touchEvent(windowNode, child);
                            end
                            SetHItemPosition(scrollNode, child, curRowIndex + 1, i, hGap, iconWidth, iconHeight, topHGap, bottomHGap, leftWGap, wGap, maxColNum, isInvert);
                            gridList[curRowIndex + 1][i] = initHandle(windowNode, child, curRowIndex * maxColNum + i);
                        end

                        -- 行指针加1
                        curRowIndex = curRowIndex + 1;

                        flag = true;

                    -- 向下移动时
                    elseif (curRowIndex > LOOP_ROW_NUM) and downOffset > gridList[curRowIndex][1]:getPositionY() + innerContainer:getPositionY() then
                        -- 取得缓存池中最后一行的节点对象
                        local temp = {};
                        for i, child in pairs(gridList[curRowIndex]) do
                            temp[i] = child;
                        end

                        -- 行指针减1
                        curRowIndex = curRowIndex - 1;

                        -- 将最后一行的节点对象移到缓存池第一行，并初始化为 curRowIndex - LOOP_ROW_NUM + 1 行的内容
                        for i, child in pairs(temp) do
                            child.index = (curRowIndex - LOOP_ROW_NUM) * maxColNum + i;
                            child:setName("item" .. (curRowIndex - LOOP_ROW_NUM) * maxColNum + i);
                            if touchEvent then
                                touchEvent(windowNode, child);
                            end
                            SetHItemPosition(scrollNode, child, curRowIndex - LOOP_ROW_NUM + 1, i, hGap, iconWidth, iconHeight, topHGap, bottomHGap, leftWGap, wGap, maxColNum, isInvert);
                            gridList[curRowIndex - LOOP_ROW_NUM + 1][i] = initHandle(windowNode, child, (curRowIndex - LOOP_ROW_NUM) * maxColNum + i);
                        end

                        flag = true;
                    end

                    scrollview.curRowIndex = curRowIndex;
                    scrollview.gridList = gridList;

                    if not flag then
                        break;
                    end
                end
            end
        end

        local function eventListener(sender,eventType)
            if eventType == ccui.ScrollviewEventType.scrolling then
                update(sender);
            end
        end
        addEventListener(scrollNode, eventListener);

        -- 记录必要的信息，比如：缓存池 gridList 和 curRowIndex
        scrollNode.gridList = gridList;
        scrollNode.curRowIndex = curRowIndex;
        scrollNode.totalNum = totalNum;
        scrollNode.maxColNum = maxColNum;
        scrollNode.wGap = wGap;
        scrollNode.hGap = hGap;
        scrollNode.iconWidth = iconWidth;
        scrollNode.iconHeight = iconHeight;
        scrollNode.topHGap = topHGap;
        scrollNode.bottomHGap = bottomHGap;
        scrollNode.leftWGap = leftWGap;
        scrollNode.isInvert = isInvert;
        scrollNode.pageRowNum = pageRowNum;
        scrollNode.rowNum = rowNum;
        scrollNode.touchEvent = touchEvent;
        scrollNode.initHandle = initHandle;
        scrollNode.windowNode = windowNode;
    else
        -- 如果所有需要画出的物件的行数小于等于当前页最大行数加三，那么一次性把物件加载出来即可
        for i = 1, rowNum do
            for j = 1, #gridList[i] do
                local child = widget:clone();

                child.index = (i - 1) * maxColNum + j;
                child:setName("item" .. (i - 1) * maxColNum + j);
                if touchEvent then
                    touchEvent(windowNode, child);
                end

                scrollNode:addChild(child);
                SetHItemPosition(scrollNode, child, i, j, hGap, iconWidth, iconHeight, topHGap, bottomHGap, leftWGap, wGap, maxColNum, isInvert);
                gridList[i][j] = initHandle(windowNode, child, (i - 1) * maxColNum + j);
            end
        end
        scrollNode.gridList = nil;
    end
end

-- 设置垂直滑动列表的偏移位置
function setScrollOffsetVertical(scrollNode, offset)
    local gridList = scrollNode.gridList;

    local innerSize = scrollNode:getInnerContainerSize();
    local scrollSize = scrollNode:getContentSize();

    if scrollSize.height - innerSize.height > offset then
        -- 超过最顶部，取最顶部的偏移位置
        offset = scrollSize.height - innerSize.height;
    elseif offset > 0 then
        -- 超过最底部，取最底部的偏移位置
        offset = 0;
    end

    -- 先将滑动列表设置偏移位置
    scrollNode:getInnerContainer():setPositionY(offset);

    if not gridList then
        -- 没有缓存池，表示所有格子数据都已创建，没必要进行后续缓存池处理
        return;
    end

    -- 重新计算偏移位置所对应的可显示区域，将缓存池中的格子初始化为可显示区域的格子数据
    local pageRowNum = scrollNode.pageRowNum;
    local topHGap = scrollNode.topHGap;
    local iconWidth = scrollNode.iconWidth;
    local iconHeight = scrollNode.iconHeight;
    local topHGap = scrollNode.topHGap;
    local bottomHGap = scrollNode.bottomHGap;
    local leftWGap = scrollNode.leftWGap;
    local wGap = scrollNode.wGap;
    local hGap = scrollNode.hGap;
    local preCurRowIndex = scrollNode.curRowIndex;
    local rowNum = scrollNode.rowNum;
    local maxColNum = scrollNode.maxColNum;
    local isInvert = scrollNode.isInvert;
    local touchEvent = scrollNode.touchEvent;
    local initHandle = scrollNode.initHandle;
    local windowNode = scrollNode.windowNode;

    local LOOP_ROW_NUM = pageRowNum + 3;

    -- 取得该偏移位置所对应缓存池的起始行索引
    local curRowIndex = math.ceil(math.max(innerSize.height - scrollSize.height - topHGap + offset, 0) / (iconHeight + hGap));
    curRowIndex = math.max(curRowIndex - 1, 1);
    curRowIndex = math.min(curRowIndex + LOOP_ROW_NUM - 1, rowNum) - LOOP_ROW_NUM + 1;
    curRowIndex = math.max(curRowIndex, 1);

    -- 复制一份缓存池
    local temp = {};
    local row = 1;
    for i = preCurRowIndex - LOOP_ROW_NUM + 1, preCurRowIndex do
        for j = 1, #gridList[i] do
            temp[row] = temp[row] or {};
            temp[row][j] = gridList[i][j];
        end
        row = row + 1;
    end

    -- 重新初始化可视区域的缓存池的格子
    row = 1;
    for i = curRowIndex, curRowIndex + LOOP_ROW_NUM - 1 do
        for j = 1, #temp[row] do
            local child = temp[row][j];
            child.index = (i - 1) * maxColNum + j;
            child:setName("item" .. (i - 1) * maxColNum + j);
            if touchEvent then
                touchEvent(windowNode, child);
            end
            SetHItemPosition(scrollNode, child, i, j, hGap, iconWidth, iconHeight, topHGap, bottomHGap, leftWGap, wGap, maxColNum, isInvert);
            gridList[i][j] = initHandle(windowNode, child, (i - 1) * maxColNum + j);
        end
        row = row + 1;
        curRowIndex = curRowIndex + 1;
    end
    curRowIndex = curRowIndex - 1;

    scrollNode.curRowIndex = curRowIndex;
    scrollNode.gridList = gridList;
end

----------------------------------------------
-- 单元格排序
-- @param totalNum      单元格总数
-- @param pageRowNum    单页可以显示下的行数
-- @param maxColNum     最大列数
function sortGridsEx(totalNum, pageRowNum, maxColNum)
    local ret = {};
    local maxRowNum = math.ceil(totalNum / maxColNum);

    -- 横向排序排序
    -- 1， 2， 3，
    -- 4,  5,  6，
    -- 7， 8，
    for i = 1, maxRowNum do
        for j = 1, maxColNum do
            local num = (i - 1) * maxColNum + j;
            if num <= totalNum then
                if not ret[i] then
                    ret[i] = {}
                end
                table.insert(ret[i], num);
            end
        end
    end

    return ret;
end

-------------------------------------------------------------------------------
-- 初始化滚动容器内的单元格（仅针对既可纵向滚动又可横向滚动的容器）
-- @param windowNode    界面节点
-- @param scrollNode    容器节点
-- @param itemNode      单元格的节点
-- @param totalNum      单元格总数
-- @param rowNum        行数
-- @param colNum        列数
-- @param wGap          单元格间距(横向)
-- @param hGap          单元格间距(纵向)
-- @param iconWidth     单元格宽度
-- @param iconHeight    单元格高度
-- @param topHGap       上方留白
-- @param bottomHGap    下方留白
-- @param leftWGap      左侧留白
-- @param rightWGap     右侧留白
-- @param touchEvent    点击事件注册函数
function initScrollGrids(windowNode, scrollNode, itemNode, totalNum, rowNum, colNum, wGap, hGap, iconWidth, iconHeight, topHGap, bottomHGap, leftWGap, rightWGap, touchEvent)
    local w = DESIGN_WIDTH;
    local h = DESIGN_HEIGHT;

    -- 计算单元格分布情况
    local gridList = sortGridsEx(totalNum, rowNum, colNum, scrollNode);

    -- 行数
    local rowNum = #gridList;
    local colNum = 0;

    -- 取所有行的列数的最大值作为最大列数
    for _, rowList in ipairs(gridList) do
        if type(rowList) == "table" then
            colNum = math.max(colNum, #rowList);
        end
    end

    -- 先计算总高度
    local totalHeight = rowNum * (iconHeight + hGap) - hGap + topHGap + bottomHGap;
    local totalWidth  = colNum * (iconWidth + wGap) - wGap + leftWGap + rightWGap;

    -- 设置滚动区域大小
    scrollNode:setInnerContainerSize(cc.size(totalWidth, totalHeight));

    local widget = replaceNodeWithWidget(itemNode);

    for i = 1, rowNum do
        for j = 1, #gridList[i] do
            local child = widget:clone();
            child:setName("item" .. gridList[i][j]);
            child.index = gridList[i][j];

            -- 计算单元格坐标
            -- 这个坐标将是单元格的描点所在
            local x = (j - 1) * (iconWidth + wGap) + iconWidth / 2 + leftWGap;
            local y = scrollNode:getInnerContainerSize().height - topHGap - (i - 1) * (iconHeight + hGap) - iconHeight / 2;

            if touchEvent then
                touchEvent(windowNode, child);
            end

            child:setPositionX(x);
            child:setPositionY(y);

            scrollNode:addChild(child)
            table.insert(scrollNode.rows, child)
        end
    end
end

----------------------------------------------
-- 上下移动时,初始化单个格子的位置
function SetHItemPosition(scrollNode, item, row, column, hGap, iconWidth, iconHeight, topHGap, bottomHGap, leftWGap, wGap, maxColNum, isInvert)
    if isInvert then
        item:setPosition((column - 1) * (iconWidth + wGap) + leftWGap, (row - 1) * (iconHeight + hGap) + bottomHGap);
    else
        item:setPosition((column - 1) * (iconWidth + wGap) + leftWGap, scrollNode:getInnerContainerSize().height - topHGap - row * (iconHeight + hGap) + hGap);
    end
end

-- 左右移动时,初始化单个格子的位置
function SetWItemPosition(scrollNode, item, column, row, wGap, iconWidth, hGap, iconHeight, topHGap, maxRowNum, leftWGap)
    item:setPosition((column - 1) * (iconWidth + wGap) + leftWGap,  scrollNode:getInnerContainerSize().height - topHGap - row * (iconHeight + hGap) + hGap );
end

----------------------------------------------
-- 滑动到最顶部
-- @param scrollview    滚动容器
function scrollToTop(scrollview)
    local viewHeight  = scrollview:getContentSize().height;
    local innerHeight = scrollview:getInnerContainerSize().height;
    scrollview:getInnerContainer():setPositionY(viewHeight - innerHeight);
end

----------------------------------------------
-- 滑动到最左侧
-- @param scrollview    滚动容器
function scrollToTopLeft(scrollview)
    scrollview:getInnerContainer():setPositionX(0);
end
